/**
 * 
 */
package ca.sfu.util;

import edu.cmu.tetrad.graph.*;
import java.util.*;
import edu.cmu.tetrad.data.*;


/**
 * @author wluoa
 *
 */
public class GraphFunctions {


	/**
	 * Construct a simple directed graph in JGraphT from a tetrad graph
	 * @param g
	 * @return
	 */
	public static org.jgrapht.graph.SimpleDirectedGraph<Node, Edge> createJGraphtFromTetrad(Graph g)
	{
		class TetradEdgeFactory implements org.jgrapht.EdgeFactory<Node, Edge>{
			private Endpoint endpoint1;
			private Endpoint endpoint2; 
			public void setEndpoints(Endpoint endpoint1, Endpoint endpoint2)
			{
				this.endpoint1 = endpoint1;
				this.endpoint2 = endpoint2;
			}
			public Edge createEdge(Node source, Node target){
				return new Edge(source, target, endpoint1, endpoint2);
			}
		}
		
		org.jgrapht.graph.SimpleDirectedGraph<Node, Edge> gJGrapht = new org.jgrapht.graph.SimpleDirectedGraph(new TetradEdgeFactory());
		
		Iterator nodeIt = g.getNodes().iterator();
		while(nodeIt.hasNext())
		{
			gJGrapht.addVertex((Node) nodeIt.next());
		}
		
		Iterator edgeIt = g.getEdges().iterator();
		while(edgeIt.hasNext())
		{
			Edge edge =(Edge) edgeIt.next();
			TetradEdgeFactory ef = (TetradEdgeFactory) gJGrapht.getEdgeFactory();
			ef.setEndpoints(edge.getEndpoint1(), edge.getEndpoint2());
			
			gJGrapht.addEdge(edge.getNode1(), edge.getNode2());			
		}
		
		return gJGrapht;
		
	}
	
	
	/**
	 * Get the graphical skeleton of a graph (i.e., every node is GraphNode)
	 * @param g
	 * @return
	 */
	public static Graph getUndirectedGraph(Graph g){
		Graph h = new Pattern();
		Iterator<Node> itNode = g.getNodes().iterator();
		
		while(itNode.hasNext())
		{
			h.addNode(new GraphNode(itNode.next().getName()));
		}
		
		Iterator<Edge> itEdge = g.getEdges().iterator();
		while(itEdge.hasNext()){
			Edge e = itEdge.next();
			h.addUndirectedEdge(new GraphNode(e.getNode1().getName()), new GraphNode(e.getNode2().getName()));
		}
	
			
		return h;
	}
	
	/**
	 * Count the number of edges (adjacencies) in both estimate and target graphs
	 * @param estimate
	 * @param target
	 * @return
	 */
	public static int countEdgeTruePositive(Graph estimate, Graph target)
	{
		Graph g = getUndirectedGraph(estimate);
		Graph h = getUndirectedGraph(target);
		return SetFunctions.intersection(g.getEdges(),h.getEdges()).size();
	}
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Dag g = new Dag();
		GraphNode a = new GraphNode("a");
		GraphNode b = new GraphNode("b");
		GraphNode c = new GraphNode("c");
		g.addNode(a); g.addNode(b); g.addNode(c);
		g.addDirectedEdge(a, b);
		g.addDirectedEdge(a, c);
		
	/*	Graph h = getUndirectedGraph(g);
		System.out.println("g = " + g.toString());
		System.out.println("h = " + h.toString());*/
		
		Graph h = new Pattern();
		Node a2 = new DiscreteVariable("a");
		Node b2 = new DiscreteVariable("b");
		Node c2 = new GraphNode("c");
		h.addNode(c2); h.addNode(b2); h.addNode(a2);
		//h.addNondirectedEdge(b2, a2);
		h.addDirectedEdge(a2, b2);
		h.addDirectedEdge(b2, c2);
		h.addDirectedEdge(c2,a2);
		
		
		System.out.println("g = " + createJGraphtFromTetrad(g));
		System.out.println("g is acyclic? " + new org.jgrapht.alg.CycleDetector(createJGraphtFromTetrad(g)).detectCycles());
		System.out.println("h = " + createJGraphtFromTetrad(h));
		System.out.println("h is acyclic? " + new org.jgrapht.alg.CycleDetector(createJGraphtFromTetrad(h)).detectCycles());
/*		System.out.println("g = " + g);
		System.out.println("h = " + h);
		System.out.println("gANDh.size = " + countEdgeTruePositive(g,h));*/
		
		
/*		System.out.println(SetFunctions.intersection(new HashSet(getUndirectedGraph(g).getEdges()),
				new HashSet(getUndirectedGraph(h).getEdges())));
		System.out.println(SetFunctions.countTruePositive(new HashSet(getUndirectedGraph(g).getEdges()),
				new HashSet(getUndirectedGraph(h).getEdges())));*/
		
	}

}
